package com.glink.manage.service.Impl;

import cn.hutool.core.date.LocalDateTimeUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.glink.common.contants.BaseCodeConstants;
import com.glink.common.exception.GeneralSimpleException;
import com.glink.common.util.BaseCommonUtils;
import com.glink.manage.common.Constants;
import com.glink.manage.domain.*;
import com.glink.manage.dto.silentresult.*;
import com.glink.manage.mapper.SilentResultMapper;
import com.glink.manage.service.*;
import com.glink.manage.vo.silentresult.SilentResultAnalysisVO;
import com.glink.manage.vo.silentresult.SilentResultPageVO;
import com.glink.manage.vo.silentresult.SilentResultWarnPageVO;
import com.glink.manage.vo.user.UserBaseInfoVO;
import com.glink.manage.vo.view.AlarmInfoVO;
import com.glink.manage.vo.ws.WarnCountVO;
import com.glink.manage.vo.ws.WarnInfoVO;
import com.glink.manage.ws.WarnWebSocketService;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author qiushaoshan
 * @since 2025-01-20
 */
@Service
@Slf4j
public class SilentResultServiceImpl extends ServiceImpl<SilentResultMapper, SilentResultBean> implements SilentResultService {

    @Autowired
    private OrgService orgService;

    @Autowired
    private UserService userService;

    @Autowired
    private ConstructionWorkService constructionWorkService;

    @Autowired
    private ConstructionWorkSiteService constructionWorkSiteService;

    @Autowired
    private PersonManageService personManageService;

    @Autowired
    private PersonViolationRegulationsRecordService personViolationRegulationsRecordService;

    @Autowired
    private PatrolIntelligentEquipService patrolIntelligentEquipService;

    @Autowired
    private WarnWebSocketService warnWebSocketService;

    @Autowired
    private SilentResultDetailService silentResultDetailService;

    @Autowired
    private AttachmentService attachmentService;

    @Autowired
    private ConstructionWorkUnitRelaService constructionWorkUnitRelaService;

    /**
     * 分页查询待处理违章
     * 1.总部管理员：人员角色标记为“总部管理员”的人,特殊，总部查所有
     * 2.项目管理员：当前相机所在工程所属项目部的人，并且此人角色是“项目部管理员”
     * 3.负责人2个：当前相机所在工程负责人和所在工程现场的负责人
     * 2025-04-23 只给监理看
     * @param dto 分页查询条件
     * @return 待处理违章
     */
    @Override
    public IPage<SilentResultPageVO> pageByPendingViolationHandling(SilentResultPageDTO dto) throws GeneralSimpleException {

        String userId = BaseCommonUtils.extractUserIdtByToken();
        if (StringUtils.isBlank(userId)) {
            throw new GeneralSimpleException("100003");
        }

        IPage<SilentResultBean> resultBeanIPage = new Page<>(dto.getPage(), dto.getSize());

        List<String> workIdList = Lists.newArrayList();
        boolean cjdwByUser = userService.checkCJDWByUser();
        boolean generalContractingUnit = userService.checkGeneralContractingUnit();
        if (!cjdwByUser && !generalContractingUnit) {//非监理单位管理员角色
            return new Page<>(dto.getPage(), dto.getSize());
        }
        //如果当前登录人员是参建单位-监理单位的负责人,那么可以查看当前所属工程下的告警信息
        PersonManageBean personManageBean = personManageService.lambdaQuery().eq(PersonManageBean::getAccountObjId, userId).one();
        if (Objects.isNull(personManageBean)) {
            return new Page<>(dto.getPage(), dto.getSize());
        }
        //查询参建单位类型是监理的责任人所属的工程id列表
        List<ConstructionWorkUnitRelaBean> constructionWorkUnitRelaBeanList = constructionWorkUnitRelaService.lambdaQuery()
                .eq(ConstructionWorkUnitRelaBean::getConstructionType, Constants.ConstructionType.supervisor)
                .eq(ConstructionWorkUnitRelaBean::getResponsiblePersonId, personManageBean.getObjId())
                .orderByDesc(ConstructionWorkUnitRelaBean::getCreateTime)
                .list();
        if (CollectionUtils.isNotEmpty(constructionWorkUnitRelaBeanList)) {
            workIdList = constructionWorkUnitRelaBeanList.stream().map(ConstructionWorkUnitRelaBean::getConstructionWorkObjId).collect(Collectors.toList());
        }
        if (CollectionUtils.isEmpty(workIdList)) {
            return new Page<>(dto.getPage(), dto.getSize());
        }

        IPage<SilentResultBean> iPage = this.lambdaQuery()
                .eq(SilentResultBean::getAnalysisStatus, BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode01)
                .in(SilentResultBean::getConstructionWorkObjId, workIdList)
                .and(w -> w.isNull(SilentResultBean::getIfWarn).or().eq(SilentResultBean::getIfWarn, ""))
                .like(StringUtils.isNotBlank(dto.getViolationType()), SilentResultBean::getViolationTypeList, dto.getViolationType())
                .orderByDesc(SilentResultBean::getCreateTime)
                .orderByDesc(SilentResultBean::getObjId)
                .page(resultBeanIPage);

        IPage<SilentResultPageVO> pageVOIPage = new Page<>(iPage.getCurrent(), iPage.getSize(), iPage.getTotal());
        List<SilentResultPageVO> pageVOList = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(iPage.getRecords())) {
            iPage.getRecords().forEach(resultBean -> {
                SilentResultPageVO resultPageVO = new SilentResultPageVO();
                resultPageVO.setObjId(resultBean.getObjId());
                resultPageVO.setCreateTime(resultBean.getCreateTime());
                resultPageVO.setViolationContent(resultBean.getViolationContentInit());
                resultPageVO.setAnalysisFilePath(resultBean.getAnalysisFilePath());
                resultPageVO.setViolationTypeList(resultBean.getViolationTypeList());
                if (StringUtils.isNotBlank(resultBean.getConstructionWorkObjId())) {
                    resultPageVO.setConstructionWorkName(constructionWorkService.findNameByObjId(resultBean.getConstructionWorkObjId()));
                }
                pageVOList.add(resultPageVO);
            });
            pageVOIPage.setRecords(pageVOList);
        }

        return pageVOIPage;
    }

    /**
     * 忽略违章
     *
     * @param objIds 处理数据
     * @return 忽略状态
     */
    @Override
    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Boolean ignoreViolations(List<String> objIds) {
        if (CollectionUtils.isNotEmpty(objIds)) {
            List<SilentResultBean> silentResultBeanList = this.lambdaQuery()
                    .in(SilentResultBean::getObjId, objIds)
                    .list();
            if (CollectionUtils.isNotEmpty(silentResultBeanList)) {
                List<SilentResultBean> resultBeanArrayList = Lists.newArrayList();
                silentResultBeanList.forEach(silentResultBean -> {
                    silentResultBean.setIfWarn(BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode02);
                    silentResultBean.setHandleTime(new Date());
                    resultBeanArrayList.add(silentResultBean);
                });
                return this.saveOrUpdateBatch(resultBeanArrayList);
            }
        }
        return false;
    }

    /**
     * 1.总部管理员：人员角色标记为“总部管理员”的人,特殊，总部查所有
     * 2.项目管理员：当前相机所在工程所属项目部的人，并且此人角色是“项目部管理员”
     * 3.负责人2个：当前相机所在工程负责人和所在工程现场的负责人
     * 2025-04-23 移除总部管理员
     * @param userId
     * @return
     * @throws GeneralSimpleException
     */
    private Integer countReadWarn(String userId) throws GeneralSimpleException {
        if (StringUtils.isBlank(userId)) {
            throw new GeneralSimpleException("100003");
        }
        
        List<String> workSiteIdList;
        String departmentAdminOrgId;
        // 总包单位管理员
        boolean generalContractingUnit = userService.checkGeneralContractingUnit(userId);
        if(generalContractingUnit){
            UserBaseInfoVO userBaseInfoVO = userService.findById(userId);
            String orgId = null;
            if(Objects.nonNull(userBaseInfoVO)){
                orgId = userBaseInfoVO.getOrgId();
            }

            if (StringUtils.isBlank(orgId)) {
                throw new GeneralSimpleException("100003");
            }
            
            List<String> workIdList = constructionWorkService.findGeneralContractingUnitAccessWorkId(orgId);
            if(CollectionUtils.isEmpty(workIdList)){
                log.info("告警统计，没有查询到总包的工程，用户ID：{}", orgId);
                return null;
            }
            workSiteIdList = constructionWorkSiteService.findGrantSiteByWorkIdIn(workIdList);
        }else{
            departmentAdminOrgId = orgService.getDepartmentOrgIdByUserId(userId);
            workSiteIdList = orgService.findWorkSiteByDepartmentAdminOrgIdAndSuperintendent(departmentAdminOrgId, userId);
        }
      
        if (CollectionUtils.isEmpty(workSiteIdList)) {
            return null;
        }

        return this.lambdaQuery()
                .eq(SilentResultBean::getIfRead, BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode02)
                .eq(SilentResultBean::getIfWarn, BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode01)
                .in(SilentResultBean::getConstructionWorkSiteObjId, workSiteIdList)
                .count();
    }

    public void countWebSocketReadWarn() {
        List<String> allUserIds = warnWebSocketService.getAllUserIds();
        if (CollectionUtils.isNotEmpty(allUserIds)) {

            allUserIds.forEach(userId -> {
                try {
                    Integer counted = countReadWarn(userId);
                    if (Objects.nonNull(counted)) {
                        sendWebSocketWarnCount(userId, counted, BaseCodeConstants.CodeType_WebSocketMsgType.KEY_WebSocketMsgType01);
                    }
                } catch (GeneralSimpleException e) {
                    throw new RuntimeException(e);
                }
            });
        }
    }

    /**
     * 处理违章
     *
     * @param dto 处理违章信息
     * @return 处理状态
     */
    @Override
    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Boolean handleViolations(SilentResultHandleDTO dto) throws GeneralSimpleException {
        boolean isWarn = false;
        SilentResultBean resultBean = this.lambdaQuery()
                .eq(SilentResultBean::getObjId, dto.getObjId())
                .one();
        if (Objects.nonNull(resultBean)) {
            isWarn = StringUtils.isBlank(resultBean.getIfWarn());

            resultBean.setViolationContent(resultBean.getViolationContentInit());
            resultBean.setViolationPerson(dto.getViolationPerson());
            resultBean.setIfWarn(dto.getIfWarn());
            resultBean.setIfRead(BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode02);
            resultBean.setHandleTime(new Date());

            boolean personStatus = false;
            if (StringUtils.isNotBlank(dto.getViolationPerson())) {
                PersonManageBean personManageBean = personManageService.lambdaQuery().eq(PersonManageBean::getObjId, dto.getViolationPerson()).one();
                if (Objects.nonNull(personManageBean)) {
                    resultBean.setViolationPersonCard(personManageBean.getCard());
                    resultBean.setViolationPersonOrgId(personManageBean.getOrgId());
                    personStatus = true;
                }
            }

            boolean status = updateById(resultBean);
            if (status) {
                if (personStatus) {
                    PersonViolationRegulationsRecordBean recordBean = new PersonViolationRegulationsRecordBean();
                    recordBean.setObjId(BaseCommonUtils.generateUUID());
                    recordBean.setPersonObjId(dto.getViolationPerson());
                    recordBean.setBehavior(resultBean.getViolationContent());
                    recordBean.setTime(resultBean.getCreateTime());
                    recordBean.setFromWarnObjId(resultBean.getObjId());
                    status = personViolationRegulationsRecordService.save(recordBean);
                }
            }

            // 告警的消息则发送webSocket
            if (status && isWarn && StringUtils.equals(resultBean.getIfWarn(), BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode01)) {
                List<String> allUserIdList = Lists.newArrayList();
                // 总部管理员ID
                List<String> headOfficeUserIdList = userService.findAllHeadOfficeUserId();
                if (CollectionUtils.isNotEmpty(headOfficeUserIdList)) {
                    allUserIdList.addAll(headOfficeUserIdList);
                }

                // 项目部管理员ID
                if (StringUtils.isNotBlank(resultBean.getProjectDepartmentObjId())) {
                    List<String> projectDepartmentAdminUserIdList = userService.findProjectDepartmentAdminUserIdByProjectDepartmentId(resultBean.getProjectDepartmentObjId());
                    if (CollectionUtils.isNotEmpty(projectDepartmentAdminUserIdList)) {
                        allUserIdList.addAll(projectDepartmentAdminUserIdList);
                    }
                }

                // 工程负责人和工程现场负责人
                if (StringUtils.isNotBlank(resultBean.getConstructionWorkObjId())) {
                    String superintendent = constructionWorkService.findSuperintendentByObjId(resultBean.getConstructionWorkObjId());
                    if (StringUtils.isNotBlank(superintendent)) {
                        allUserIdList.add(superintendent);
                    }
                }

                if (StringUtils.isNotBlank(resultBean.getConstructionWorkSiteObjId())) {
                    String superintendent = constructionWorkSiteService.findSuperintendentByObjId(resultBean.getConstructionWorkSiteObjId());
                    if (StringUtils.isNotBlank(superintendent)) {
                        allUserIdList.add(superintendent);
                    }
                }

                // 发送webSocket信息
                if (CollectionUtils.isNotEmpty(allUserIdList)) {
                    allUserIdList = allUserIdList.stream().distinct().collect(Collectors.toList());

                    sendWebSocketWarnInfo(resultBean, allUserIdList);
                }
            }
            return status;
        }
        return false;
    }

    /**
     * 发送webSocket告警
     *
     * @param resultBean 结果
     * @param userIdList 用户
     */
    private void sendWebSocketWarnInfo(SilentResultBean resultBean, List<String> userIdList) {
        WarnInfoVO warnInfoVO = new WarnInfoVO();
        SilentResultWarnPageVO silentResultWarnPageVO = beanToWarnPageVO(resultBean);
        BeanUtils.copyProperties(silentResultWarnPageVO, warnInfoVO);
        warnInfoVO.setMsgType(BaseCodeConstants.CodeType_WebSocketMsgType.KEY_WebSocketMsgType02);
        if (Objects.nonNull(resultBean.getCreateTime())) {
            warnInfoVO.setCreateTime(BaseCommonUtils.DATE_FORMAT_DAY_5.format(resultBean.getCreateTime()));
        }

        warnWebSocketService.sendMessage(JSON.toJSONString(warnInfoVO), userIdList);
    }

    /**
     * 发送webSocket告警统计
     *
     * @param userId 用户信息
     */
    private void sendWebSocketWarnCount(String userId, Integer count, String msgType) {
        WarnCountVO warnCountVO = new WarnCountVO();
        warnCountVO.setMsgType(msgType);
        warnCountVO.setMsgCount(String.valueOf(count));
        warnWebSocketService.sendMessage(JSON.toJSONString(warnCountVO), Collections.singletonList(userId));
    }

    /**
     * 分页查询告警信息
     *  1.总部管理员：人员角色标记为“总部管理员”的人,特殊，总部查所有
     *  2.项目管理员：当前相机所在工程所属项目部的人，并且此人角色是“项目部管理员”
     *  3.负责人2个：当前相机所在工程负责人和所在工程现场的负责人
     *  2025-04-23 移除总部管理员
     * @param dto 告警查询
     * @return 告警信息
     */
    @Override
    public IPage<SilentResultWarnPageVO> pageByWarn(SilentResultWarnPageDTO dto) throws GeneralSimpleException {

        String userId = BaseCommonUtils.extractUserIdtByToken();
        if (StringUtils.isBlank(userId)) {
            throw new GeneralSimpleException("100003");
        }
        IPage<SilentResultBean> resultBeanIPage = new Page<>(dto.getPage(), dto.getSize());

        boolean admin = userService.checkAdminByUser();
        
        List<String> workSiteIdList;
        List<String> grantWorkSiteIdList = Lists.newArrayList();
        String departmentAdminOrgId;
        if (!admin) {

            // 总包单位管理员
            boolean generalContractingUnit = userService.checkGeneralContractingUnit();
            if(generalContractingUnit){
                List<String> workIdList = constructionWorkService.findGeneralContractingUnitAccessWorkId();
                if(CollectionUtils.isEmpty(workIdList)){
                    log.info("告警，没有查询到总包的工程，用户ID：{}", userId);
                    return new Page<>(dto.getPage(), dto.getSize());
                }
  
                workSiteIdList = constructionWorkSiteService.findGrantSiteByWorkIdIn(workIdList);
            }else{
                // 项目部
                departmentAdminOrgId = orgService.getDepartmentOrgIdByUserId();
                workSiteIdList = orgService.findWorkSiteByDepartmentAdminOrgIdAndSuperintendent(departmentAdminOrgId, userId);    
            }
            
            if (CollectionUtils.isEmpty(workSiteIdList)) {
                return new Page<>(dto.getPage(), dto.getSize());
            } else {
                // 查询授权的场站
                grantWorkSiteIdList = constructionWorkSiteService.findGrantSiteByObjIdIn(workSiteIdList);
                grantWorkSiteIdList = grantWorkSiteIdList == null ? Lists.newArrayList() : grantWorkSiteIdList;
            }
        } else {
            if (StringUtils.isNotBlank(dto.getConstructionWorkSiteObjId())) {
                // 查询授权的场站
                constructionWorkSiteService.checkGrantByObjId(dto.getConstructionWorkSiteObjId());
            }
            workSiteIdList = Lists.newArrayList();
        }
        // 施工现场，查询当天的告警
        LocalDateTime today = LocalDateTimeUtil.now();
        LocalDateTime startDateTime = LocalDateTimeUtil.beginOfDay(today);
        LocalDateTime endDateTime = LocalDateTimeUtil.endOfDay(today);

        List<String> finalWorkSiteIdList = workSiteIdList;
        IPage<SilentResultBean> iPage = this.lambdaQuery()
                .and(!admin, w -> w
                        .eq(SilentResultBean::getIfWarn, BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode01)
                        .in(SilentResultBean::getConstructionWorkSiteObjId, finalWorkSiteIdList)
                        .eq(StringUtils.isNotEmpty(dto.getConstructionWorkSiteObjId()), SilentResultBean::getConstructionWorkSiteObjId, dto.getConstructionWorkSiteObjId())
                        .between(StringUtils.isNotEmpty(dto.getConstructionWorkSiteObjId()), SilentResultBean::getHandleTime, startDateTime, endDateTime)
                        .eq(StringUtils.isNotEmpty(dto.getConstructionWorkObjId()), SilentResultBean::getConstructionWorkObjId, dto.getConstructionWorkObjId())
                )
                // 系统管理员查看抓图失败和分析失败的告警
                .and(admin, w -> w.eq(SilentResultBean::getPickStatus, BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode02)
                        .or()
                        .eq(SilentResultBean::getAnalysisStatus, BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode02)
                )

                .orderByDesc(SilentResultBean::getHandleTime)
                .orderByDesc(SilentResultBean::getCreateTime)
                .orderByDesc(SilentResultBean::getObjId)
                .page(resultBeanIPage);

        IPage<SilentResultWarnPageVO> pageVOIPage = new Page<>(iPage.getCurrent(), iPage.getSize(), iPage.getTotal());
        List<SilentResultWarnPageVO> pageVOList = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(iPage.getRecords())) {
            List<String> finalGrantWorkSiteIdList = grantWorkSiteIdList;
            iPage.getRecords().forEach(resultBean -> {
                SilentResultWarnPageVO silentResultWarnPageVO = beanToWarnPageVO(resultBean);
                if (CollectionUtils.isNotEmpty(finalGrantWorkSiteIdList) && StringUtils.isNotBlank(silentResultWarnPageVO.getConstructionWorkSiteObjId())) {
                    if (finalGrantWorkSiteIdList.contains(silentResultWarnPageVO.getConstructionWorkSiteObjId())) {
                        silentResultWarnPageVO.setIfGrant(BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode01);
                    } else {
                        silentResultWarnPageVO.setIfGrant(BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode02);
                    }
                }

                pageVOList.add(silentResultWarnPageVO);
            });
            pageVOIPage.setRecords(pageVOList);
        }

        return pageVOIPage;
    }

    /**
     * 实体转告警分页VO
     *
     * @return 告警VO
     */
    private SilentResultWarnPageVO beanToWarnPageVO(SilentResultBean resultBean) {
        SilentResultWarnPageVO resultPageVO = new SilentResultWarnPageVO();
        resultPageVO.setObjId(resultBean.getObjId());
        resultPageVO.setAnalysisFilePath(resultBean.getAnalysisFilePath());
        if (StringUtils.isBlank(resultBean.getViolationContent())) {
            resultPageVO.setViolationContent(resultBean.getViolationContentInit());
        } else {
            resultPageVO.setViolationContent(resultBean.getViolationContent());
        }

        // 违章人员姓名
        if (StringUtils.isNotBlank(resultBean.getViolationPerson())) {
            resultPageVO.setViolationPersonName(personManageService.findNameByObjId(resultBean.getViolationPerson()));
        }
        // 抓图失败的，没有告警处理时间，需要用创建时间
        if (Objects.nonNull(resultBean.getHandleTime())) {
            resultPageVO.setCreateTime(resultBean.getHandleTime());
        } else {
            resultPageVO.setCreateTime(resultBean.getCreateTime());
        }


        // 项目部名称
        if (StringUtils.isNotBlank(resultBean.getProjectDepartmentObjId())) {
            resultPageVO.setProjectDepartmentObjId(resultBean.getProjectDepartmentObjId());
            resultPageVO.setProjectDepartmentName(orgService.findOrgNameByOrgId(resultBean.getProjectDepartmentObjId()));
        }

        // 施工工程名称
        if (StringUtils.isNotBlank(resultBean.getConstructionWorkObjId())) {
            resultPageVO.setConstructionWorkObjId(resultBean.getConstructionWorkObjId());
            resultPageVO.setConstructionWorkName(constructionWorkService.findNameByObjId(resultBean.getConstructionWorkObjId()));
        }

        // 施工现场名称
        if (StringUtils.isNotBlank(resultBean.getConstructionWorkSiteObjId())) {
            resultPageVO.setConstructionWorkSiteObjId(resultBean.getConstructionWorkSiteObjId());
            resultPageVO.setConstructionWorkSiteName(constructionWorkSiteService.findNameByObjId(resultBean.getConstructionWorkSiteObjId()));
        }

        resultPageVO.setIfRead(resultBean.getIfRead());
        return resultPageVO;
    }

    /**
     * 根据创建时间查询待分析图片
     *
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return 待分析图片
     */
    @Override
    public List<SilentResultAnalysisVO> findToBeAnalyzedByCreateTimeBetween(LocalDateTime startTime, LocalDateTime endTime) {
        List<SilentResultBean> resultBeanList = this.lambdaQuery()
                .ge(SilentResultBean::getCreateTime, startTime)
                .le(SilentResultBean::getCreateTime, endTime)
                .and(w -> w.isNull(SilentResultBean::getAnalysisStatus).or().eq(SilentResultBean::getAnalysisStatus, ""))
                // 抓图成功
                .eq(SilentResultBean::getPickStatus, BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode01)
                .orderByAsc(SilentResultBean::getCreateTime)
                .orderByAsc(SilentResultBean::getObjId)
                .list();

        List<SilentResultAnalysisVO> analysisVOList = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(resultBeanList)) {
            resultBeanList.forEach(resultBean -> {
                SilentResultAnalysisVO analysisVO = new SilentResultAnalysisVO();
                analysisVO.setObjId(resultBean.getObjId());
                analysisVO.setFilePath(resultBean.getFilePath());
                analysisVOList.add(analysisVO);
            });
        }

        return analysisVOList;
    }

    @Override
    public List<SilentResultAnalysisVO> findAllToBeAnalyzedByCreateTimeLe(LocalDateTime time) {
        List<SilentResultBean> resultBeanList = this.lambdaQuery()
                .le(SilentResultBean::getCreateTime, time)
                .and(w -> w.isNull(SilentResultBean::getAnalysisStatus).or().eq(SilentResultBean::getAnalysisStatus, ""))
                // 抓图成功
                .eq(SilentResultBean::getPickStatus, BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode01)
                .orderByAsc(SilentResultBean::getCreateTime)
                .orderByAsc(SilentResultBean::getObjId)
                .list();

        List<SilentResultAnalysisVO> analysisVOList = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(resultBeanList)) {
            resultBeanList.forEach(resultBean -> {
                SilentResultAnalysisVO analysisVO = new SilentResultAnalysisVO();
                analysisVO.setObjId(resultBean.getObjId());
                analysisVO.setFilePath(resultBean.getFilePath());
                analysisVOList.add(analysisVO);
            });
        }

        return analysisVOList;
    }

    /**
     * 已读消息
     *
     * @param dto 已读告警ID
     * @return 已读状态
     */
    @Override
    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean readWarn(SilentResultWarnReadDTO dto) throws GeneralSimpleException {

        String userId = BaseCommonUtils.extractUserIdtByToken();

        if (CollectionUtils.isNotEmpty(dto.getWarnInfoIdList())) {
            return this.lambdaUpdate()
                    .set(SilentResultBean::getIfRead, BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode01)
                    .set(SilentResultBean::getReadTime, new Date())
                    .set(SilentResultBean::getReadUser, userId)
                    .in(SilentResultBean::getObjId, dto.getWarnInfoIdList()).update();
        }
        return false;
    }

    /**
     * 保存更新结果数据
     *
     * @param silentResultBean 任务结果
     * @param detailBeanList   结果详情
     */
    @Override
    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void saveAndDetail(SilentResultBean silentResultBean, List<SilentResultDetailBean> detailBeanList) {
        boolean status = false;
        if (Objects.nonNull(silentResultBean)) {

            status = saveAnalysisInfo(silentResultBean);
        }
        if (status && CollectionUtils.isNotEmpty(detailBeanList)) {
            silentResultDetailService.lambdaUpdate().eq(SilentResultDetailBean::getResultObjId, silentResultBean.getObjId()).remove();
            silentResultDetailService.saveBatch(detailBeanList);
        }
    }

    /**
     * 统计待处理违章数
     * 1.总部管理员：人员角色标记为“总部管理员”的人,特殊，总部查所有
     * 2.项目管理员：当前相机所在工程所属项目部的人，并且此人角色是“项目部管理员”
     * 3.负责人2个：当前相机所在工程负责人和所在工程现场的负责人
     * 2025-04-23 待处理违章只给监理看
     */
    @Override
    public void countPendingViolationHandling() {
        List<String> allUserIds = warnWebSocketService.getAllUserIds();
        if (CollectionUtils.isNotEmpty(allUserIds)) {

            allUserIds.forEach(userId -> {
                try {
                    boolean cjdwByUser = userService.checkCJDWByUser(userId);
                    boolean generalContractingUnit = userService.checkGeneralContractingUnit(userId);
                    List<String> workIdList;
                    if (!cjdwByUser && !generalContractingUnit) {
                        return;
                    }
                    PersonManageBean personManageBean = personManageService.lambdaQuery().eq(PersonManageBean::getAccountObjId, userId).one();
                    if (Objects.isNull(personManageBean)) {//非监理单位管理员角色
                        return;
                    }
                    List<ConstructionWorkUnitRelaBean> constructionWorkUnitRelaBeanList = constructionWorkUnitRelaService.lambdaQuery()
                            .eq(ConstructionWorkUnitRelaBean::getResponsiblePersonId, personManageBean.getObjId())
                            .eq(ConstructionWorkUnitRelaBean::getConstructionType, Constants.ConstructionType.supervisor)
                            .list();
                    if (CollectionUtils.isEmpty(constructionWorkUnitRelaBeanList)) {
                        return;
                    }
                    workIdList = constructionWorkUnitRelaBeanList.stream().map(ConstructionWorkUnitRelaBean::getConstructionWorkObjId).collect(Collectors.toList());
                    Integer count = 0;
                    if(CollectionUtils.isNotEmpty(workIdList)){
                        count = this.lambdaQuery()
                                .eq(SilentResultBean::getAnalysisStatus, BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode01)
                                .in(SilentResultBean::getConstructionWorkObjId, workIdList)
                                .and(w -> w.isNull(SilentResultBean::getIfWarn).or().eq(SilentResultBean::getIfWarn, ""))
                                .count();
                    }

                    count = count == null ? 0 : count;
                    sendWebSocketWarnCount(userId, count, BaseCodeConstants.CodeType_WebSocketMsgType.KEY_WebSocketMsgType04);
                } catch (GeneralSimpleException e) {
                    throw new RuntimeException(e);
                }
            });
        }
    }

    /**
     * 下载FTP图片
     *
     * @param type     1原图，2结果图
     * @param resultId 结果ID
     * @param response 返回
     */
    @Override
    public void downloadPicByFtp(String type, String resultId, HttpServletResponse response) {
        SilentResultBean silentResultBean = getById(resultId);
        if (Objects.isNull(silentResultBean)) {
            return;
        }

        String path = "";
        if (StringUtils.equals(type, "1")) {
            path = silentResultBean.getFilePath();
        } else if (StringUtils.equals(type, "2")) {
            path = silentResultBean.getAnalysisFilePath();
        }

        if (StringUtils.isNotBlank(path)) {
            attachmentService.downloadPicByFtp(path, response);
        }
    }

    /**
     * 根据工程信息统计当天的告警信息
     *
     * @param workIdList 工程ID
     * @param startDate  开始时间
     * @param endDate    结束时间
     * @return 告警信息
     */
    public List<AlarmInfoVO> countAlarmInfoTodayByWorkIdInAndHandleTimeBetween(List<String> workIdList, LocalDateTime startDate, LocalDateTime endDate) {
        return this.baseMapper.countAlarmInfoTodayByWorkIdInAndHandleTimeBetween(workIdList, startDate, endDate, BaseCodeConstants.CodeType_05.KEY_AlgCode);
    }

    /**
     * 更新结果信息，抓图失败
     */
    @Override
    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void updateBaseInfoByError() {
        List<SilentResultBean> resultBeanList = this.lambdaQuery()
                .eq(SilentResultBean::getPickStatus, BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode02)
                .isNull(SilentResultBean::getAnalysisStatus)
                .list();
        if (CollectionUtils.isNotEmpty(resultBeanList)) {
            resultBeanList.forEach(resultBean -> {
                resultBean.setAnalysisStatus(BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode02);
                resultBean.setAnalysisTime(new Date());
                resultBean.setViolationContentInit(resultBean.getReason());
                resultBean.setIfRead(BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode02);
                saveAnalysisInfo(resultBean);
            });
        }
    }

    /**
     * 保存分析识别结果
     *
     * @param silentResultBean 结果
     */
    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean saveAnalysisInfo(SilentResultBean silentResultBean) {
        if (Objects.nonNull(silentResultBean)) {
            if (StringUtils.isNotBlank(silentResultBean.getEquipId())) {
                // 查询设备信息，获取所属工程和施工现场
                PatrolIntelligentEquip intelligentEquip = patrolIntelligentEquipService.getById(silentResultBean.getEquipId());
                if (Objects.nonNull(intelligentEquip)) {
                    // 设置所属的工程和施工现场
                    silentResultBean.setConstructionWorkObjId(intelligentEquip.getConstructionWorkId());
                    silentResultBean.setConstructionWorkSiteObjId(intelligentEquip.getConstructionWorkSiteId());

                    // 查询工程信息获取所属项目部
                    if (StringUtils.isNotBlank(intelligentEquip.getConstructionWorkId())) {
                        ConstructionWorkBean constructionWorkBean = constructionWorkService.getById(intelligentEquip.getConstructionWorkId());
                        if (Objects.nonNull(constructionWorkBean)) {
                            // 设置所属项目部信息
                            silentResultBean.setProjectDepartmentObjId(constructionWorkBean.getProjectDepartmentObjId());
                        }
                    }
                }
            }

            boolean status = updateById(silentResultBean);
            if (status) {
                if (StringUtils.equals(silentResultBean.getAnalysisStatus(), BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode02)) {
                    // 分析失败，给系统管理员发送告警信息
                    // 系统管理员ID
                    List<String> userIdList = Lists.newArrayList();
                    List<String> headOfficeUserIdList = userService.findAllSystemAdminUserId();
                    if (CollectionUtils.isNotEmpty(headOfficeUserIdList)) {
                        userIdList.addAll(headOfficeUserIdList);
                    }
                    sendWebSocketWarnInfo(silentResultBean, userIdList);
                }
            }
            return status;
        }
        return false;
    }
}
